﻿// Decompiled with JetBrains decompiler
// Type: KKtLib.DIVA
// Assembly: PD_Tool_Private, Version=0.4.5.3, Culture=neutral, PublicKeyToken=null
// MVID: 8A8DE4DE-5B2D-492A-9C2E-FC536B2E689B
// Assembly location: F:\divax\data\PCSB01007\rom\PD_Tool_Private.exe

using KKtLib.Types;
using System;
using System.IO;

namespace KKtLib
{
  public class DIVA
  {
    public string file = "";
    private readonly sbyte[] ima_index_table = new sbyte[8]
    {
      (sbyte) -1,
      (sbyte) -1,
      (sbyte) -1,
      (sbyte) -1,
      (sbyte) 2,
      (sbyte) 4,
      (sbyte) 6,
      (sbyte) 8
    };
    private readonly short[] ima_step_table = new short[89]
    {
      (short) 7,
      (short) 8,
      (short) 9,
      (short) 10,
      (short) 11,
      (short) 12,
      (short) 13,
      (short) 14,
      (short) 16,
      (short) 17,
      (short) 19,
      (short) 21,
      (short) 23,
      (short) 25,
      (short) 28,
      (short) 31,
      (short) 34,
      (short) 37,
      (short) 41,
      (short) 45,
      (short) 50,
      (short) 55,
      (short) 60,
      (short) 66,
      (short) 73,
      (short) 80,
      (short) 88,
      (short) 97,
      (short) 107,
      (short) 118,
      (short) 130,
      (short) 143,
      (short) 157,
      (short) 173,
      (short) 190,
      (short) 209,
      (short) 230,
      (short) 253,
      (short) 279,
      (short) 307,
      (short) 337,
      (short) 371,
      (short) 408,
      (short) 449,
      (short) 494,
      (short) 544,
      (short) 598,
      (short) 658,
      (short) 724,
      (short) 796,
      (short) 876,
      (short) 963,
      (short) 1060,
      (short) 1166,
      (short) 1282,
      (short) 1411,
      (short) 1552,
      (short) 1707,
      (short) 1878,
      (short) 2066,
      (short) 2272,
      (short) 2499,
      (short) 2749,
      (short) 3024,
      (short) 3327,
      (short) 3660,
      (short) 4026,
      (short) 4428,
      (short) 4871,
      (short) 5358,
      (short) 5894,
      (short) 6484,
      (short) 7132,
      (short) 7845,
      (short) 8630,
      (short) 9493,
      (short) 10442,
      (short) 11487,
      (short) 12635,
      (short) 13899,
      (short) 15289,
      (short) 16818,
      (short) 18500,
      (short) 20350,
      (short) 22385,
      (short) 24623,
      (short) 27086,
      (short) 29794,
      short.MaxValue
    };
    public DIVA.DIVAFile Data;

    public DIVA()
    {
      this.Data = new DIVA.DIVAFile();
      this.file = "";
    }

    public DIVA(string filepath)
    {
      this.Data = new DIVA.DIVAFile();
      this.file = filepath;
    }

    public void DIVAReader()
    {
      if (!File.Exists(this.file + ".diva"))
        return;
      this.Data = new DIVA.DIVAFile();
      KKtLib.IO io1 = KKtLib.IO.OpenReader(this.file + ".diva");
      if (io1.ReadString(4L) == nameof (DIVA))
      {
        io1.ReadInt32();
        this.Data.Size = io1.ReadInt32();
        this.Data.SampleRate = io1.ReadInt32();
        this.Data.SamplesCount = io1.ReadInt32();
        io1.ReadInt64();
        this.Data.Channels = io1.ReadInt32();
        this.Data.Name = io1.ReadString(32L);
        KKtLib.IO io2 = KKtLib.IO.OpenWriter(this.file + ".wav", true);
        io2.Seek(44L, SeekOrigin.Begin);
        HalfByte halfByte = (HalfByte) 0;
        int[] numArray1 = new int[this.Data.Channels];
        int[] numArray2 = new int[this.Data.Channels];
        sbyte[] numArray3 = new sbyte[this.Data.Channels];
        while (io1.Position < io1.Length)
        {
          for (byte index = 0; (int) index < this.Data.Channels; ++index)
          {
            this.IMADecoder((byte) io1.ReadHalfByte(), ref numArray1[(int) index], ref numArray2[(int) index], ref numArray3[(int) index]);
            io2.Write((float) numArray1[(int) index] / 32768f);
          }
        }
        Main.WAVHeader Header = new Main.WAVHeader()
        {
          Bytes = 4,
          Channels = this.Data.Channels,
          Format = 3,
          SampleRate = this.Data.SampleRate,
          Size = io2.Position - 46
        };
        io2.Write(Header, 0L);
        io2.Close();
      }
      io1.Close();
    }

    public void DIVAReadToArray()
    {
      this.Data = new DIVA.DIVAFile();
      if (!File.Exists(this.file + ".diva"))
        return;
      KKtLib.IO io1 = KKtLib.IO.OpenReader(this.file + ".diva");
      if (io1.ReadString(4L) == nameof (DIVA))
      {
        KKtLib.IO io2 = new KKtLib.IO((Stream) new MemoryStream(), false);
        io1.ReadInt32();
        this.Data.Size = io1.ReadInt32();
        this.Data.SampleRate = io1.ReadInt32();
        this.Data.SamplesCount = io1.ReadInt32();
        io1.ReadInt64();
        this.Data.Channels = io1.ReadInt32();
        this.Data.Name = io1.ReadString(32L);
        this.Data.Name = Path.GetFileNameWithoutExtension(this.file);
        HalfByte halfByte = (HalfByte) 0;
        int[] numArray1 = new int[this.Data.Channels];
        int[] numArray2 = new int[this.Data.Channels];
        sbyte[] numArray3 = new sbyte[this.Data.Channels];
        byte[] numArray4 = new byte[4];
        while (io1.Position < io1.Length)
        {
          for (byte index = 0; (int) index < this.Data.Channels; ++index)
          {
            this.IMADecoder((byte) io1.ReadHalfByte(), ref numArray1[(int) index], ref numArray2[(int) index], ref numArray3[(int) index]);
            io2.Write((double) numArray2[(int) index] / 32768.0, (short) 4, (ushort) 3);
          }
        }
        Main.WAVHeader Header = new Main.WAVHeader()
        {
          Bytes = 4,
          Channels = this.Data.Channels,
          Format = 3,
          SampleRate = this.Data.SampleRate,
          Size = io2.Position - 46
        };
        io2.Write(Header, 0L);
        this.Data.Data = io2.ToArray();
      }
      io1.Close();
    }

    private byte[] BuildWavHeader(Main.WAVHeader Header, short Bytes)
    {
      KKtLib.IO io = new KKtLib.IO((Stream) new MemoryStream(), false);
      io.Write(Header);
      byte[] array = io.ToArray();
      io.Close();
      return array;
    }

    public void DIVAWriter()
    {
      if (!File.Exists(this.file + ".wav"))
        return;
      KKtLib.IO io1 = KKtLib.IO.OpenReader(this.file + ".wav");
      KKtLib.IO io2 = KKtLib.IO.OpenWriter(this.file + ".diva", true);
      this.Data = new DIVA.DIVAFile();
      Main.WAVHeader wavHeader = io1.ReadWAVHeader();
      if (wavHeader.IsSupported)
      {
        this.Data.Channels = wavHeader.Channels;
        this.Data.SampleRate = wavHeader.SampleRate;
        io2.Seek(64L, SeekOrigin.Begin);
        HalfByte halfByte = (HalfByte) 0;
        double[] numArray1 = new double[this.Data.Channels];
        int[] numArray2 = new int[this.Data.Channels];
        int[] numArray3 = new int[this.Data.Channels];
        sbyte[] numArray4 = new sbyte[this.Data.Channels];
        while (io1.Position < wavHeader.Size + wavHeader.HeaderSize)
        {
          for (byte index = 0; (int) index < wavHeader.Channels; ++index)
          {
            numArray1[(int) index] = io1.ReadWAVSample(wavHeader.Bytes, wavHeader.Format);
            HalfByte val = (HalfByte) this.IMAEncoder(numArray1[(int) index], ref numArray2[(int) index], ref numArray3[(int) index], ref numArray4[(int) index]);
            io2.Write(val);
          }
          io2.CheckWrited();
          ++this.Data.SamplesCount;
        }
        io2.Seek(0L, SeekOrigin.Begin);
        io2.Write(nameof (DIVA));
        io2.Write(0);
        io2.Write(io2.Length - 64);
        io2.Write(this.Data.SampleRate);
        io2.Write(this.Data.SamplesCount);
        io2.Write(0);
        io2.Write(0);
        io2.Write(this.Data.Channels);
      }
      io1.Close();
      io2.Close();
    }

    private void IMADecoder(
      byte value,
      ref int current,
      ref int currentclamp,
      ref sbyte stepindex)
    {
      short num1 = this.ima_step_table[(int) stepindex];
      int num2 = (int) num1 >> 3;
      if (((int) value & 1) == 1)
        num2 += (int) num1 >> 2;
      if (((int) value & 2) == 2)
        num2 += (int) num1 >> 1;
      if (((int) value & 4) == 4)
        num2 += (int) num1;
      current = currentclamp;
      if (((int) value & 8) == 8)
      {
        currentclamp -= num2;
        current = currentclamp;
        currentclamp = Math.Max(currentclamp, (int) short.MinValue);
      }
      else
      {
        currentclamp += num2;
        current = currentclamp;
        currentclamp = Math.Min(currentclamp, (int) short.MaxValue);
      }
      stepindex += this.ima_index_table[(int) value & 7];
      if (stepindex < (sbyte) 0)
        stepindex = (sbyte) 0;
      if (stepindex <= (sbyte) 88)
        return;
      stepindex = (sbyte) 88;
    }

    private byte IMAEncoder(
      double sample,
      ref int current,
      ref int currentclamp,
      ref sbyte stepindex)
    {
      bool flag = false;
      byte num1 = 0;
      short num2 = this.ima_step_table[(int) stepindex];
      sample = (double) this.CDTB(sample * 32768.0);
      int num3 = (int) sample - current;
      if (num3 < 0)
      {
        flag = true;
        num3 = -num3;
      }
      int num4 = (int) num2 >> 3;
      if (num3 > (int) num2)
      {
        num1 |= (byte) 4;
        num3 -= (int) num2;
        num4 += (int) num2;
      }
      short num5 = (short) ((int) num2 >> 1);
      if (num3 > (int) num5)
      {
        num1 |= (byte) 2;
        num3 -= (int) num5;
        num4 += (int) num5;
      }
      short num6 = (short) ((int) num5 >> 1);
      if (num3 > (int) num6)
      {
        num1 |= (byte) 1;
        num4 += (int) num6;
      }
      if (flag)
      {
        currentclamp -= num4;
        current = currentclamp;
        currentclamp = Math.Max(currentclamp, (int) short.MinValue);
      }
      else
      {
        currentclamp += num4;
        current = currentclamp;
        currentclamp = Math.Min(currentclamp, (int) short.MaxValue);
      }
      stepindex += this.ima_index_table[(int) num1 & 7];
      if (stepindex < (sbyte) 0)
        stepindex = (sbyte) 0;
      if (stepindex > (sbyte) 88)
        stepindex = (sbyte) 88;
      if (flag)
        num1 |= (byte) 8;
      return num1;
    }

    private int CDTB(double c)
    {
      c = c * 10.0 % 10.0 <= 5.0 ? Math.Floor(c) : Math.Ceiling(c);
      return (int) c;
    }

    public struct DIVAFile
    {
      public int Size;
      public int Channels;
      public int SampleRate;
      public int SamplesCount;
      public string Name;
      public byte[] Data;
    }
  }
}
